home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-11-16 | 29.8 KB | 1,782 lines | [TEXT/MPS ] |
- #############################################################################
- Recipes for MPW C++ 1.0a4
- Kent Sandvik DTS 15 September 1991
-
- Permission to republish this is granted, as long as the contents
- are not modified/altered/shortened in any way without consulting the author first.
-
- Place in MPW Folder, and put following line (example) in UserStartup:
- AddMenu Special 'C++ Recipes/1' 'Open "{MPW}Recipes.C++"'
- ^ triggered from option-1
-
- Please redirect any comments, bug reports and such to:
- ksand@apple.com (Usenet, Internet)
- KSAND (AppleLink)
- 75300, 1331 (CompuServe)
-
- References:
- C++ Programming Language (second edition), Bjarne Stroustrup
- Annotated C++ Reference Manual, Ellis & Stroustrup
- All kinds of private notes/hacks (Usenet comp.lang.c++, CompuServe)
-
- Future plans:
- * more material, bug fixes, better explanations
- * 411 (template/lookup support), or something more hypertext:ish
-
- Thanks!
- Johan Strandberg, Common Knowledge
-
- #############################################################################
-
- // C+ class test template
-
- #include <stream.h>
-
- class TFoo {
- public:
- TFoo(); // constructor
- ~TFoo(); // destructor
-
- protected:
- long fField;
- private:
- };
-
-
- // Method implementations
-
- TFoo::TFoo() // constructor
- {
- cout << "inside TFoo constructor\n";
- }
-
- TFoo::~TFoo() // destructor
- {
- // empty for the moment
- }
-
-
- class TBar : public TFoo{
- public:
- TBar() { cout << "inside TBar constructor\n";}
- virtual void Member();
- };
-
- void TBar::Member()
- {
- cout << "inside TBar::Member\n";
- }
-
-
- TBar *aBar;
-
- main()
- {
- aBar = new TBar;
- return 0;
- }
-
-
- // volatile macro
-
- #define VOLATILE(a) ((void) &a)
-
-
- // global scope operator
-
- int x;
-
- void func()
- {
- int x = 1; // use local x
- ::x = 2; // use global x
- }
-
-
- // void pointers - can be made to point at anything
-
- void* malloc(unsigned size); // C style memory allocation
- void free(void*);
-
- void func()
- {
- int* pi = (int *)malloc(10*sizeof(int));
- char* pc = (char *)malloc(10);
- // ...
- free(pi);
- free(pc);
- }
-
-
- // pointers
-
- int* pi; // pointer to int
- char** cpp; // pointer to array to char
- int (*vp)[10]; // pointer to array of 10 ints
- int (*fp) (char, char*); // pointer to function taking
- // (char, char*), returning int
-
- char c1 = 'a'; // c1 contains 'a'
- char* p = &c1; // p contains address of c1
- char c2 = *p; // c2 contains 'a'
-
- size_t strlen(char* p)
- {
- size_t i = 0;
- while(*p++) i++;
- return i;
- }
-
- // faster pointer string comparison, produces better code in most platforms
-
- int strlen(const char* p)
- {
- register char *q = p;
- while(*q++)
- return q - p - 1;
- }
-
-
- // arrays
-
- float v[3]; // array of 3 floats
- int a[3][5]; // 2-dimensional array of ints (3 times 5)
- char* vpc[32]; // array of 32 char pointers
-
- int v1[1] = {1, 2, 3, 4}; // assigment of array elements
-
-
-
- // pointers and arrays
-
- char* p = &alpha[0]; // make p point at start of alpha array
- char* p = alpha; // same semantics!
-
- extern "C" int strlen(const char*);
- void func()
- {
- char v[] ="Jeff Steven"
- char* p = v;
- strlen(p);
- strlen(v); // both gives same value
- }
-
-
- // structures
-
- struct address {
- char* name;
- long number;
- char* street;
- char* town;
- char state[2];
- long zip;
- };
-
- address js;
- js.name = "Jeff Sandvik";
- js.number = 20200;
-
-
- address js = { // struct assignment
- "Jeff Sandvik",
- 20200, "Lucille Ave",
- "Cupertino", {'C','A'}, 95104
- };
-
-
- void printAddress(address p) // struct pointer handling
- {
- cout << p->name << '\n'
- << p->number << ' ' << p->street << '\n'
- << p->town << '\n'
- << p->state[0] << p->state[1]
- << ' ' << p->zip <<'\n'
- }
-
- address current;
-
- address setCurrent(address next) // address handling
- {
- address prev = current;
- current = next;
- return prev;
- }
-
- struct link { // struct self referencing
- link* previous;
- link* next;
- };
-
-
-
- // typedef
-
- typedef char* Pchar;
- Pchar p1, p2;
- char p3 = p1;
-
-
- // references (&) cmp Pascal VAR
-
- int i = 1; // example
- int& r = i;
- int x = r; // x = 1;
- r = 2; // i = 2;
-
- void incr(int&a) {a++;} // function call
-
- void func()
- {
- int x = 1;
- incr(x); // x = 2;
- }
-
-
- // const
-
- const int model = 100;
- model = 200; // error!
-
- const char* pc = "abc"; // const pc data
- pc[3] ='a'; // error!
- pc = "def"; // ok
-
- char* const cp = "abc"; // constant pointer
- cp[3] = 'a'; // ok
- cp = "def"; // error!
-
- const char *const pc "abc"; // data and pointer constant
-
- char* strcpy(char* p, const char* q); // can't modify q
-
-
- // enums
-
- enum {eRed, eBlue, eGreen}; // enum list, eRed = 0, eBlue = 1...
- enum {eRed = 200, eBlue, eGreen = 300}; // eBlue = 201
-
- enum eColors {eRed, eBlue, eGreen}; // named enum
- eColors returnColor();
-
- eColors theColor;
-
- switch (theColor){
- case eRed:
- // do something
- break;
- case eBlue:
- // do something
- break;
- case eGreen:
- // do something
- break;
- default:
- // do something
- break;
- }
-
- class foo{
- public:
- enum eColors{
- eRed, eBlue, eGreen};
- //...
- };
-
- myClass.fColor = foo::eRed;
-
-
- // bitfields
-
- struct ASICReg {
- unsigned enable: 1; // one bit
- unsigned page: 3; // three bits
- unsigned : 1; // unused
- unsigned mode: 2; // two bits
- unsigned : 4; // unused
- unsigned access: 1; // one bit
- unsigned length: 1;
- unsigned non_res: 1;
- };
-
- ASICReg* SR = (sreg *) 0xA800; // fictiv address, memory mapped I/O
- // ...
-
- if (SR->access) { // true?
- // clean up the state
- SR->access = 0;
- }
-
-
- // unions
-
- struct entry {
- char* name;
- char type; // tagged value for union
- union {
- char* stringValue; // char string type = 's'
- int intValue; // or int variable type = 'i'
- };
- };
-
- union foo { // named union
- int i;
- int* p;
- };
-
-
- // modulo
-
- const int RANGE = 100;
- int i;
-
- i %= RANGE; // i is in the range 0...RANGE-1
-
-
- // left shift
-
- int i =0x8000;
- i <<= 1; // left shift one step
-
-
- // bitwise XOR
-
- int i = 0x8000;
- i ^= 0x3000; // note, no space between ^ and =!!!
-
- // bitwise OR
-
- int i = 0x8000;
- i |= 0x3000;
-
- // bitwise AND
-
- int i = 0x8000;
- i &= 0x3000;
-
-
- // error stream
-
- int numErrors;
-
- double error(const char* s)
- {
- cerr <<"error: " << s << "\n";
- numErrors++;
- return 1;
- }
-
-
- // type conversion
-
- int foo = 56;
- float bar = float(foo);
-
- char* p = (char *)0xA800; // typecast of address
- typedef char* Address;
- Address p = Address(0xA800); // same as above
-
-
- // free store (new, delete, set_new_handler...)
-
- main() // simple example
- {
- char *p = saveString("foobar");
- delete[] p; // note new 2.0 delete syntax
- }
-
- char* saveString(const char* p)
- {
- char* s = new char[strlen(p) + 1];
- strcpy(s,p);
- return s;
- }
-
- TFoo *aFoo = new TFoo; // create object in the free store (heap on MacOS)
-
- #include <stream.h>
- #include <new.h>
-
- void OutofStore()
- {
- cerr << "operator new failed : out of store\n";
- exit(1);
- }
-
- main()
- {
- set_new_handler(&OutOfStore); // give address to handler
- char* p = new char[100000000000];
- cout <<"what, it works..., address = ", long(p) << '\n';
- // new returns 0 if it can't find enough memory - test for NULL
- }
-
-
-
- // stack based objects
-
- void func()
- {
- TFoo aFoo; // local -> placed on the stack
- aFoo.Beep();
- } // removed from stack automatically
-
-
- // ? : conditional expression
-
- max = (a <= b) ? b : a;
-
-
- // linkage to non-C++ code (no function name mangling
-
- #ifdef __cplusplus
- extern "C" {
- #endif
- pascal Handle NewHandle(Size byteCount)
- #pragma parameter DisposHandle(__A0)
- pascal void DisposHandle(Handle h)
- = 0xA023;
- #ifdef __cplusplus
- }
- #endif
-
- extern "C" {
- char* strcpy(char*, const char*);
- int strcmp(const char*, const char*);
- // ...
- }
-
- extern "C" {
- #include "myCHeaderFiles.h"
- }
-
-
- // recursion
-
- int fac(int n) {return (n > 1) ? n * fac(n-1) : 1;}
-
-
- // overloaded function names
-
- void print(int); // integer print
- void print(const char*); // string print
-
-
- // default function arguments
-
- void print(int value, int base=10);
- //...
- print(30); // will use base=10 inside print
-
- void foo(int, char*, int = 0, char* = 0);
- // have to define defaults from right!
-
-
-
- // unspecified amount of function args
-
- int printf(const char ...);
-
-
- // pointers to functions
-
- void error(char* p) {/* ... */}
- void (*efunc)(char*); // pointer to function
-
- void func()
- {
- efunc = &error; // give address to function ptr
- (*efunc)("mayday"); // call the function via ptr
- }
-
- typedef void (*PF)();
-
- PF editOps[] = { // edit operations
- &cut, &paste, ©
- };
-
- PF fileOps[] = {
- &new, &save, &close
- };
-
- PF MenuEntry = editOps;
- //...
- (*MenuEntry[3])(); // selected copy! trigger copy function
-
-
- // macros
-
- #define print(a,b) cout << (a) << (b) // argument usage
- #define forever for(;;)
- #define MIN(a,b) (((a)<(b))?(a):(b))
-
-
- // this pointer
-
- always defined as X *const this; where X is the name of the class
-
- class X{
- int m;
- public:
- int readm() {return this->m;} // makes things more clear!
-
-
- class dlink{
- dlink* previous;
- dlink* successor;
- public:
- void append(dlink*);
- // ...
- };
-
- void dlink::append(dlink* p )
- {
- p->successor = successor;
- p->previous = this;
- successor->previous = p;
- successor = p;
- }
-
- dlink* listHead;
- void func(dlink* a, dlink* b)
- {
- // ...
- listHead->append(a);
- listHead->append(b);
- }
-
-
- // const member function
-
- class X{
- int m;
- public:
- readme() const {return m;} // const member function, read-only
- writeme(int i) {m = i;}
- };
-
- // you are able to change a value through an explicit this cast:
-
- class X{
- int m;
- public:
- // ...
- void implicitCheat() const {m++;} // error!
- void explicitCheat() const { ((X *)this)->m++;} // ok
- };
-
-
- // const classes
-
- void func(X& mutable, const X& constant)
- {
- mutable.readme(); // ok
- mutable.writeme(7); // ok
- constant.readme(); // ok
- constant.writeme(7); // error
- }
-
-
- // constructors
-
- class TDate{
- // ...
- TDate(int day, int month, long year); // constructor
- TDate(int month, long year); // other form
- TDate(long); // 910915, ANSI standard
- TDate(); // default today's date
- TDate(const char*); // string "Sun 15 Sept 1991"
- TDate(int d = 0, int m =0, long year = 0); // default values
- };
-
- TDate today(15,9,1991); // stack based class
- TDate tomorrow("Mon 16 Sept 1991");
- TDate now; // today's date
- TDate d = today; // default copy constructor! bitwise copy
-
- TDate::TDate(int d, int m, long y) // constructor function declaration
- {
- // ...
- }
-
-
- // destructors
-
- class TStack{
- int size;
- char* top;
- char* s;
- public:
- TStack(int sz) {top = s = new char[size = sz];}
- ~TStack() { delete [] s;} // destructor
- void push(char c) {*top++ = c;}
- void pop() { return *--top;}
- };
-
- void func()
- {
- TStack s1(100);
- TStack s2(200);
- s1.push('a');
- s2.push('b');
- char ch = s2.pop();
- cout << ch << '\n';
- } // automatic call of destructor
-
-
-
- // inline calls (see ARM 102 for more info when compiler will not inline
-
- class TFoo{
- public:
- void func1(){ /*...*/} // this code is inlined
- void func2();
- };
-
- inline void
- TFoo::func2()
- { // this code is inlined
- // ...
- }
-
-
- // friends
-
- class x {
- friend class y; // class y has access to x's private parts
- // ...
- };
-
- class x{
- friend void y::f(); // y::f() member function has access to
- //... // x's private parts
- };
-
-
- // class member name qualification
-
- class X{
- int m;
- public:
- int getm() const { return m;}
- void setm(int m) { X::m = m;} // name qualification
- };
-
- class TFile(){
- // ...
- int open(const char*, const char*);
- };
-
- int TFile::open(const char* name, const char* spec)
- {
- // ...
- if(::open(name,flag)){ // stdclib open called
- // ...
- }
- // ...
- }
-
-
- // nested classes
-
- class TSet {
- struct setmem{
- int mem;
- setmem* next;
- setmem(int m, setmem* n) {mem = m; next = n;}
- };
- setmem* first; // nested class struct
- public:
- TSet() {first = NULL;}
- insert(){first = new setmem(m, first);}
- // ...
- };
-
-
- // nicer with friends:
-
- class TSetmem{
- friend class TSet; // access to members of TSet only
- int mem;
- setmem* next;
- setmem(int m, setmem* n) { mem = m, next = n;}
- // other useful members
- };
-
- class TSet{
- setmem* first;
- public:
- TSet() {first = NULL;}
- insert(int m) {first = new setmem(m, first);}
- // ...
- };
-
- class X{ // name scoping
- private:
- struct M1 { int m;}
- public:
- struct M2 { int m;}
- M1 f(M2); // member function
- };
-
- void func()
- {
- M1 a; // error, 'M1' not in scope
- M2 b; // ok
- X::M1 c; // error, 'M1' private
- X::M2 d; // ok
- }
-
-
- // static class members
-
- class TTask{
- public:
- // ...
- static TTask* chain; // static field, one copy of the TTask only
- static void Schedule(); // static member function
- // ...
- };
-
- TTask* TTask::chain = NULL;
- void TTask::Schedule() {/* ....*/};
-
- ....
- if(TTask::chain == NULL){ // must be qualified by class name
- // do something
- }
-
- TTask::Schedule(); // call the static member function
-
-
- // pointers to members
-
- typedef long (TFoo::*Function)();
- enum eGenerator{SIMPLE, PRACTICAL, COMPLEX};
-
- class TFoo{
- private:
- Function fGenerator; // pointer to Generate function
- int fVal;
- public:
- TFoo(eGenerator);
- long Simple() { return 2;}
- long Practical() { return 4;};
- long Complex() { return 6;}
- long Generate() { return this->*fGenerator();} // use the function fGenerator is pointing at
- };
-
- TFoo::TFoo(eGenerator theGenerator)
- {
- switch(theGenerator){ // set pointer to defined function
- case SIMPLE:
- this->fGenerator = &TFoo:Simple;
- break;
- case PRACTICAL:
- this->fGenerator = &TFoo::Practical;
- break;
- case COMPLEX:
- this->fGenerator = &TFoo:Complex;
- }
- }
-
-
-
-
-
- // class objects as members
-
- class TClassDef{
- table members;
- int numMembers;
- // ...
- TClassDef(int size);
- ~TClassDef();
- };
-
- TClassDef::TClassDef(int size): members(size) // pass information for init
- {
- numMembers = size;
- // ...
- }
-
-
- // arrays of class objects
-
- TTable tbl[10]; // will generate an array of 10 TTable objects
-
-
- // new/delete operator overloading
-
- class TName {
- public:
- char* string;
- TName* next;
- double value;
-
- TName(char*, double name*);
- ~TName();
-
- void* operator new(size_t);
- void operator delete(void*, size_t);
- private:
- enum {N_ALL = 128};
- static name* nfree;
- };
-
- void* TName::operator new(size_t)
- register TName* p = nfree; // first allocate
-
- if(p)
- nfree = p->next;
- else{
- TName* q = (TName *) new char[N_ALL*sizeof(name)];
- for(p = nfree = &q[N_ALL -1]; q < p; p--)
- p->next = p - 1;
- p->next = NULL;
- }
- return p;
- }
-
- void TName::operator delete(void* p, size_t)
- {
- ((TName *)p)->next = nfree;
- nfree = (TName *)p;
- }
-
- //....
- *TName::nfree = 0; // explicit initialization of the value
-
-
-
- // derived classes
-
- class TEmployee{
- private:
- char* name;
- short age;
- short department;
- public:
- TEmployee();
- print() const {/*...*/}
- TEmployee* next;
- }
-
- class TManager : public TEmployee{
- TEmployee* group;
- short level;
- public:
- TManager();
- print() const {/*...*/}
- };
-
- void TEmployee::print()
- {
- cout <<"Employee information...\n";
- }
-
- void TManager::print()
- {
- TEmployee::print(); // print employee information
- cout <<"Manager information...\n";
- }
-
- void func()
- {
- TManager m1, m2;
- TEmployee e1, e2;
- TEmployee* elist;
-
- elist = &m1; // put m1 on elist
- m1.next = &e2; // put e1 on elist
- e1.next = &m2;
- m2.next = &e2;
- e2.next = NULL; // last in the elist
- }
-
- void g()
- {
- TManager MM;
- Temployee* pe = &MM; // ok
-
- TEmployee ee;
- manager* PM = ⅇ // error, not every TEmployee is a TManager
-
- PM->level = 2; // won't work, no space for level
-
- PM = (TManager *) pe; // ok
- PM->level = 2; // ok
- }
-
-
- // derived constructors/destructors
- // class objects are constructed from the bottom up, first the base,
- // then the members, then the derived class itself. They are destroyed
- // in the opposite order
-
- class TEmployee{
- // ...
- public:
- TEmployee(char* n, int d);
- };
-
- class TManager:: public TEmployee{
- // ....
- public:
- TManager(char* n, int l, int d);
- };
-
- TEmployee::TEmployee(char* n, int d)
- :name(n), department(d)
- {
- next = list;
- list = this;
- }
-
- TManager::TManager(char* n, int l, int d)
- :TEmployee(n,d), level(l), group(0)
- {
- //...
- }
-
-
- // class hierarchies
-
- class TEmployee { /* .... */ };
- class TManager: public TEmployee {/* .... */};
- class TDirector: public TManager {'* .... */};
- class TTemporary {/* ....*/};
-
-
- // multiple inheritance
-
- class TConsultant: public TManager, public TTemporary {/* .... */};
-
- class TTask{
- //
- virtual info* debug();
- };
-
- class TDisplayed{
- // ...
- virtual info* debug();
- };
-
-
- class TSatellite: public TTask, public TDisplayed{
- // ...
- };
-
- void func(TSatellite& s) // ambiguity with member function names
- {
- s.draw(); // TDisplayed::draw()
- s.delay(10); // TTask::delay(int x);
- s.xmit(); // TSatellite::Xmit()
-
- info* d_info = s.debug; // ambiguity problems!
- d_info = s.TTask::debug(); // ok
- d_info = s.TDisplayed::debug() // ok
-
- // with pointers, TSatellite *s
- d_info = s->TTask::debug();
- d_info = s->TDisplayed::debug();
- }
-
- // better to define new member functions inside TSatellite!
-
- class TSatellite: public TTask, public TDisplayed{
- // ...
-
- info* satelliteDebug()
- {
- info* d1 = TTask::debug();
- info* d2 = TDisplayed::debug();
- return d1.merge(d2);
- }
- };
-
-
- // virtual functions
-
- class TEmployee {
- char* name;
- short department;
- // ...
- TEmployee* next;
- static TEmployee* list;
- public:
- TEmployee(char* n, int d);
- // ..
- static void printList();
- virtual void print() const; // virtual function, can be
- }; // overridden
-
- ....
- void TEmployee::print() const
- {
- cout << name << '\t' << department << '\n';
- // ...
- }
-
- class TManager::public TEmployee{
- TEmployee* group;
- short level;
- // ...
- public:
- TManager(char* n, int l, int d);
- // ...
- void print const(); // we could override this - virtual
- };
-
- ....
- void TManager::print() const
- {
- cout << level << '\n';
- //...
- }
-
-
- // abstract classes
- // pure virtual functions
-
- class TShape{ // has pure virtual function = abstract class
- // ...
- public:
- virtual void rotate(int x) =0; // pure virtual function
- };
-
- class TMyShape{
- // ...
- public:
- virtual void rotate(int x){/* ... */} // have to create this member function
- };
-
- ...
- TShape aShape; // error!
- TMyShape anotherShape; // ok
-
-
- // virtual base classes
-
- class TWindow{
- // window information
- void _Draw(); // internal window draw
- virtual void Draw(); { _Draw();} // calls by default _Draw()
- };
-
- class TWindowBorder : public virtual TWindow{
- // border information
- void _Draw(); // draw border
- void Draw();
- };
-
- class TWindowMenu : public virtual TWindow{
- // menu information
- void _Draw(); // draw menu
- void Draw();
- };
-
- class TWindowBorderMenu : public virtual TWindow,
- public TWindowBorder, public TWindowMenu{
- // ...
- void _Draw(); // draw specific stuff
- void Draw();
- };
-
- // every class defined virtual base class will be represented by a *single*
- // object of that class.
-
-
- void TWindowBorder::Draw()
- {
- TWindow::Draw();
- _Draw(); // draw the border
- }
-
- void TWindowMenu::Draw()
- {
- TWindow::Draw();
- _Draw(); // draw the menu
- }
-
- void TWindowBorderMenu::Draw()
- {
- TWindow::Draw();
- TWindowBorder::Draw();
- TWindowMenu::Draw();
- _Draw(); // draw specific stuff
- }
-
-
- // access control
- // private (class only), protected (shareable by inheritance),
- // public (open)
-
- class X{
- private: // no definition = private
- enum {A, B};
- void f(int x);
- int a;
- };
-
- void X::f(int x)
- {
- if (x < A) f(x+B);
- a++;
- }
-
- void g(X& x)
- {
- int i = X::A; // error, X::A is private
- x.f(2); // error, X::f() is private
- x.a++; // error X::a is private
- }
-
-
- // protected members
-
- class X{
- // private by default
- int priv;
- protected:
- int prot;
- public:
- int publ;
- void m();
- };
-
- void X::m()
- {
- priv = 1; // ok
- prot = 2; // ok
- publ = 3; // ok
- }
-
- class Y : public X{
- void mDerived();
- };
-
- void Y::mDerived()
- {
- priv = 1; // error, priv is private inside X
- prot = 2; // ok, inherited
- publ = 3; // ok, public class
- }
-
- void f(Y* p)
- {
- p->priv = 1; // error, priv is private
- p->prot = 2; // error, prot is protected, and no inheritance
- p->publ = 3; // ok, public class
- }
-
-
- // access to base class
-
- class X{
- public:
- int a;
- // ...
- };
-
- class Y1 : public X { /*...*/}
- class Y2 : protected X {/* ... */}
- class Y3 : private X {/* ... */} // private default
-
- void f(Y1* p1, Y2* p2, Y3* p3)
- {
- X* q1 = p1; // ok, X is a public base class of Y1
- p1->a = 7; // ok, internal reference to private field
- q1= p2; // error, X is a protected base of Y2
- p2->a = 7; // error,
- q1 = p3; // error, X is a private base of Y3
- p3->a = 7; // error
- }
-
-
- // virtual destructors
-
- class TFoo{
- public:
- TFoo(); // constructor
- virtual ~TFoo(); // virtual destructor
- // ...
- };
-
- // this makes it possible for the compiler to keep track of each destructor
- // and the ordering. Most destructors should be virtual!
-
-
-
- // new - placement operator
-
- class X{
- // ...
- public:
- X(int);
- };
-
- void* operator new(size_t, void* p) {return p;}
-
- char buffer[sizeof(X)];
-
- void f(int i)
- {
- X* p = new(buffer) X(i); // place X in buffer!
- // ...
- }
-
- class TArena{
- // ...
- virtual void* alloc(size_t) = 0;
- virtual void free(void) = 0;
- };
-
- void* operator new(size_t, sz, Arena* a)
- {
- return a.alloc(size);
- }
- ...
- extern Arena* Persistent;
- extern Arena* Shared;
-
- void g(int i)
- {
- X* p = new(Persistent) X(i); // X in persistent storage
- X* q = new(Shared) X(i); // X in shared memory
- // ...
- }
-
- void h(X* p)
- {
- p->~X(); // call destructor
- Persistent->free(p); // free actual memory
- }
-
-
- // operator overloading
-
- class TComplex{ // class definition
- double re, im;
- public:
- TComplex(double r, double i=0) {re = r, im =i;}
- friend complex operator+(TComplex, TComplex);
- friend complex operator*(TComplex, TComplex);
-
- TComplex& operator +=(TComplex);
- TComplex& operator -=(TComplex);
- };
-
- inline TComplex& TComplex::operator+=(TComplex a)
- {
- re += a.re;
- im += a.im;
- return this;
- }
-
- inline TComplex operator+(TComplex a, TComplex b)
- {
- return TComplex(a.re+b.re, a.im + b.im);
- }
-
-
- void f() // usage
- {
- complex a = complex(1, 3.1);
- complex b = complex(1.2, 2);
- complex c = b;
-
- a = b + c;
- b = b + c * a;
- c = a * b + complex(1,2);
-
- complex d = operator+(a,b); // explicit call
- complex e = 23; // takes default i value
- }
-
-
- // conversion operators
-
- class TTiny{
- char v;
- void assign(int i)
- {
- if (i>63) {error("range error"); v = i&~63;}
- v = i;
- }
- public:
- TTiny(int i) {assign(i);}
- TTiny(const TTiny& t) { v = t.v;}
- TTiny& operator= (const TTiny& t)
- { v = t.v; return *this;}
- TTiny& operator=(int i) {assign(i); return *this;}
- operator int() { return v;} // conversion operator!
- };
-
- void main()
- {
- TTiny c1 = 2;
- TTiny c2 = 62;
- TTiny c3 = c2 - c1; // c3 = 60
- TTiny c4 = c3; // no range check, not necessary
- int i = c1 + c2; // i = 64
- c1 = c2 + 2*c1; // c1 = 2
- c2 = c1 - i; // c2 = 2
- c3 = c2; // no range check, not necessary
- }
-
-
- // copy constructors
-
- class TString{
- char* p;
- int size; // of vector pointed to by p
-
- TString(int sz) { p = new char[size=sz];}
- ~TString() { delete [] p;}
- TString& operator=(const TString&);
- TString(const TString&); // copy constructor!
- };
-
- TString::TString(const TString& a) // (if not defined, bitwise copy generated by compiler
- {
- p = new char[size =a.size];
- strcpy(p, a.p);
- }
-
- TString& TString::operator=(const TString& a)
- {
- if(this != &a){
- delete [] p;
- p = new char[size = a.size];
- strcpy(p, a.p);
- }
- return *this;
- }
-
- void f()
- {
- TString s1(10);
- TString s2 = s1; // initialization, not assignment
- }
-
- // memberwise initalization
-
- class TString{
- public:
- TString(const TString& s)
- //
- private:
- short len;
- char str[255];
- };
-
- TString(const TString&)
- {
- this->len = s.len;
- this->str = s.str;
- }
-
- //...
- TString foo = bar;
-
-
- // subscripting - operator [] overload
-
- #include <string.h>
-
- class TAssoc{
- struct pair{
- char* name;
- int val;
- };
- pair* vector;
- int max;
- int nfree;
-
- TAssoc(const& TAssoc&); // prevent copying
- TAssoc& operator=(const TAssoc&); // prevent assignment
- public:
- TAssoc(int);
- int& operator[](const char*); // operator [] overload
- void PrintAll();
- };
-
- TAssoc::TAssoc(int s)
- {
- max = (s < 16) ? s : 16;
- nfree = 0;
- vector = new pair[max];
- }
-
- int& TAssoc::operator[](const char* p)
- // maintain a set of pairs, search for p, return a reference to the
- // integer part of its "pair",, make a new "pair" if "p" has not been seen
-
- register pair* pp;
-
- for(pp = vector + free - 1 ; vector <= pp; pp--)
- if( strcmp(p,pp->name) == 0 ) return pp->val;
-
- if(nfree == max){ // overflow, grow the vector
- pair* newvec = new pair[max*2];
- for(int i=0; i < max; i++)
- newvec[i] = vector[i];
- delete [] vector;
- vector = newvector;
- max = 2*max;
- }
-
- pp = &vector[nfree++];
- pp->name = new char[strlen(p) + 1];
- strcpy(pp->name, p);
- pp->val = 0; // initial value
- return pp->val;
- }
-
- void TAssoc::PrintAll()
- {
- for(int i=0; i <nfree; i++)
- cout <<vector[i].name << ": " << vector[i].val << "\n";
- }
-
- main()
- {
- const MAX = 256;
- char buf[MAX];
-
- TAssoc aVector(512);
- while (cin >>buf) aVector[buf]++;
- aVector.PrintAll();
- }
-
-
- // function call overload
-
- class TAssoc{
- friend class TAssocIterator;
- pair* vec;
- int max;
- int free;
- public:
- TAssoc(int);
- int& operator[](const char*);
- };
-
- class TAssocIterator{
- TAssoc* cs; // current TAssoc array
- int i; // current index
- public:
- TAssocIterator(const TAssoc& s) {cs = &s; i = 0;}
- pair* operator()() // function call operator overload
- { return (i < cs->free) ? &cs->vec[i++] : NULL;}
- };
-
- main() // count the occurrences of each word on input
- {
- const MAX = 256;
- char buf[MAX];
- TAssoc aVector(256);
-
- while(cin>>buf) aVector[buf]++;
- TAssocIterator next(aVector);
- pair* p;
-
- while(p = next())
- cout <<p->name << ": " << p->val << '\n';
- }
-
-
- // dereferencing operator ->
-
- class TPtr{
- // ...
- X* operator->(); // class X
- };
-
- void f(TPtr p) // usage
- {
- p->m = 7; // (p.operator->())->m = 7;
- }
-
- // smart pointers
-
- class TRecPtr{
- Rec* inCoreAddress;
- const char* ID;
- // ...
- public:
- TRecPtr(const char* p)
- : identifier(p) {inCoreAddress = NULL;}
- ~TRecPtr()
- { WriteToDisk(inCoreAddress, ID);}
- Rec* operator->();
- };
-
- Rec* TRecPtr::operator->()
- {
- if(inCoreAddress == NULL)
- inCoreAddress = ReadFromDisk(ID);
- return inCoreAddress;
- }
-
- main(int argc, const char* argv) // usage
- {
- for(int i = argc; i; i--){
- TRecPtr p(argv[i]);
- p->update();
- }
- }
-
-
- // increment/decrement operator overloading
-
- class TCheckedPtrToT{
- T* p;
- T* array;
- int size;
- public:
- // bind to array 'a' of size 's' initial value 'p'
- TCheckedPtrToT(T* p, T* a, int s);
-
- // bind to single objec initial value 'p'
- TCheckedPtrToT(T* p);
-
- T* operator++(); // prefix
- T* operator++(int); // postfix - works from Cfront 3.0 forward
-
- T* operator--(); // prefix
- T* operator--(int); // postfix - works from Cfront 3.0 forward
-
- T& operator*(); // prefix
- };
-
- void func(T a) // example of use
- {
- T v[200];
- TCheckedPtrToT p(&v[0],v,200); // create object
- p.operator--(1);
- p.operator*() = a; // runtime error, 'p' out of range
- p.operator++();
- p.operator*() = a; // ok
- }
-
-
- // string class implementation
-
- #include <iostream.h>
- #include <string.h>
-
- class TString{
- struct srep{
- char* s; // pointer to data
- int n; // reference count
- srep() { n =1;}
- };
- srep* p;
-
- public:
- TString(const char*); // TString x = "abc";
- TString(); // TString x;
- TString(const TString&); // TString x = TString ...
- TString& operator=(const char*);
- TString& operator=(const TString&);
- ~TString();
- char& operator[](int i);
-
- friend ostream& operator<<(ostream&, const TString&);
- friend istream& operator>>(istream&, TString&);
-
- friend int operator==(const TString &x, const char *s)
- { return strcmp(x.p->s, s) == 0;}
-
- friend int operator==(const TString &x, const TString &y)
- { return strcmp(x.p->s, y.p->s) == 0;}
-
- friend int operator !=(const TString &x, const char *s)
- { return strcmp(x.p->s, s) != 0;}
-
- friend int operator !=(const TString &x, const Tstring &y)
- { return strcmp(x.p->s, y.p->s) != 0;}
- };
-
- TString::TString() // constructor
- {
- p = new srep;
- p->s = NULL;
- }
-
- TString::TString(const TString& x) // copy constructor
- {
- x.p->n++;
- p = x.p;
- }
-
- TString::TString(const char* s)
- {
- p = new srep;
- p->s = new char[strlen(s) + 1];
- strcpy(p->s, s);
- }
-
- TString::~TString()
- {
- if(--p->n == 0){
- delete [] p->s;
- delete p;
- }
- }
-
-
- TString& TString::operator=(const char *s)
- {
- if(p->n > 1){ // disconnect self
- p->n--;
- p = new srep;
- }
- else // free old string
- delete[] p->s;
-
- p->s = new char[strlen(s) + 1];
- strcpy(p->s, s);
- return *this;
- }
-
-
- TString& TString::operator=(const TString& x)
- {
- x.p->n++; // protect against 'st = st'
- if(--p->n == 0){
- delete[] p-s;
- delete p;
- }
- p = x.p;
- return *this;
- }
-
-
- ostream& operator<<(ostream& s, const TString& x)
- {
- return s << x.p->s << " [" << x.p->n <<"]\n";
- }
-
-
- istream& operator>>(istream& s, TString& x)
- {
- char buf[256];
- s.get(buf,256);
- char c;
- if(s.get(c) && c != '\n'){
- // buffer overflow, line longer than buffer
- }
-
- x = buf;
- cout << "echo: " << x <<'\n';
- return s;
- }
-
-
- void error(const char* p)
- {
- cerr << p << '\n';
- exit(1);
- }
-
-
- char& TString::operator[](int i)
- {
- if (i<0 || strlen(p->s) < i) error ("index out of range");
- return p->s[i];
- }
-
-
- int main() // example of usage
- {
- TString x[100];
-
- cout <<"here we go!\n";
-
- for(int n = 0; cin >x[n]; n++){
- if(n == 100){
- error("too many strings");
- return 99;
- }
-
- TString y;
- cout << (y = x[n]);
- if(y == "done") break;
- }
-
- cout << "here we go back again!\n";
- for(int i = n-1; 0<=i; i--) cout << x[i];
-
- return 0;
- }
-
-
- // casting of class
-
- class TBase { ... } b;
- class Tdpriv : private TBase { ... } dv;
- class Tdpub : public TBase { ... } db;
- foo(TBase b) { ... }
-
- foo(b); // legal
- foo(db); // legal
- foo(dv); // NOT legal!!
- foo((TBase)dv); // legal
-
-
- // access control - adjustment
-
- class TBase{
- public:
- virtual void func(void){};
- };
-
- class derived1 : private TBase{
- public:
- TBase::func;
- };
-
- class derived2 : private derived1{
- public:
- void func(void){};
- };
-
- main()
- {
- derived2* foo = new derived2;
- return 0;
- }
-
-
- // more esoteric tricks
-
-
- // passing variable arguments to constructor
-
- #include <stdarg.h>
-
- class TBase { ... TBase(int); Init(va_list); ... };
-
- class TDerived : public TBase { ... TDerived(int, ...); ... };
-
- TDerived::TDerived(int i, ... ) : TBase(i) {
- va_list ap;
- va_start(ap, i);
- Init(ap);
- va_end(ap);
- }
-
-
-
-
-
-
-
-
-
-
-
-